package com.h3c.ptability.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.eos.common.constant.StatusCodeEnum;
import com.eos.common.custom.BusinessException;
import com.eos.common.util.Result;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Charsets;
import com.h3c.ptability.bo.DeptManagerBO;
import com.h3c.ptability.bo.SearchDeptsManagersBO;
import com.h3c.ptability.cache.PtEnumCache;
import com.h3c.ptability.dto.ExcelFileDTO;
import com.h3c.ptability.dto.OptionsDTO;
import com.h3c.ptability.dto.PtDeptDTO;
import com.h3c.ptability.dto.eos.EosSpecialDeptDto;
import com.h3c.ptability.entity.PtDept;
import com.h3c.ptability.service.IPtDeptService;
import com.h3c.ptability.service.IPtEnumService;
import com.h3c.ptability.support.ResultData;
import com.h3c.ptability.utils.AppBusinessException;
import com.h3c.ptability.utils.BusiEnumDefine;
import com.h3c.ptability.utils.CommonUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Optional;

/**
 * Copyright (C), 2022-2022, h3c
 * FileName: PtDeptController
 *
 * @Author: l22886
 * @Date: 2022-03-14
 * Description: pt_dept controller
 * Version: 1.0
 */
@Api(tags = " PtDept 接口")
@CrossOrigin
@Slf4j
@RestController
@RequestMapping(value = "/ptDept", produces = "application/json;charset=utf-8")
public class PtDeptController {

    @Resource
    private IPtDeptService ptDeptService;

    @Resource
    private IPtEnumService ptEnumService;

    /**
     * @title: queryFuzzyListForPage
     * @description: 列表分页模糊查询
     * @params: [ paramsDTO, currentPage, pageSize ]
     * @return: org.springframework.http.ResponseEntity
     * @createTime: 2022-03-14
     * @version: 1.0
     * @author: l22886
     */
    @ApiOperation(value = "列表分页查询", notes = "列表分页查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "paramsDTO", value = "实体参数信息", required = true, dataType = "PtDeptDTO", paramType = "query"),
            @ApiImplicitParam(name = "currentPage", value = "当前页", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "一页数据条数", required = true, dataType = "Integer", paramType = "query")
    })
    @RequestMapping(value = "/queryFuzzyListForPage", method = RequestMethod.GET)
    public Result queryFuzzyListForPage(@ModelAttribute PtDeptDTO paramsDTO,
                                        @RequestParam(name = "currentPage", required = true) Integer currentPage,
                                        @RequestParam(name = "pageSize", required = true) Integer pageSize) {
        log.info("准备执行  列表分页模糊查询，传入的参数为：" + JSON.toJSONString(paramsDTO));
        //分页
        Page page = PageHelper.startPage(currentPage, pageSize);
        //执行
        List<PtDeptDTO> resultDTOList = ptDeptService.selectFuzzyByDto(paramsDTO);
        PageInfo<PtDeptDTO> pageInfo = page.toPageInfo();
        pageInfo.setList(resultDTOList);
        log.info("执行列表分页模糊查询完成，准备返回的结果为：" + JSON.toJSONString(pageInfo));
        return new Result(true, 20000, "列表分页模糊查询成功", pageInfo);
    }

    /**
     * @title: queryListForPage
     * @description: 列表分页精确查询
     * @params: [ paramsDTO, currentPage, pageSize ]
     * @return: org.springframework.http.ResponseEntity
     * @createTime: 2022-03-14
     * @version: 1.0
     * @author: l22886
     */
    @ApiOperation(value = "列表分页查询", notes = "列表分页查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "paramsDTO", value = "实体参数信息", required = true, dataType = "PtDeptDTO", paramType = "query"),
            @ApiImplicitParam(name = "currentPage", value = "当前页", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "一页数据条数", required = true, dataType = "Integer", paramType = "query")
    })
    @RequestMapping(value = "/queryListForPage", method = RequestMethod.GET)
    public Result queryListForPage(@ModelAttribute PtDeptDTO paramsDTO,
                                   @RequestParam(name = "currentPage", required = true) Integer currentPage,
                                   @RequestParam(name = "pageSize", required = true) Integer pageSize) {
        log.info("准备执行  列表分页查询，传入的参数为：" + JSON.toJSONString(paramsDTO));
        //分页
        Page page = PageHelper.startPage(currentPage, pageSize);
        //执行
        List<PtDeptDTO> resultDTOList = ptDeptService.selectFuzzyByDto(paramsDTO);
        PageInfo<PtDeptDTO> pageInfo = page.toPageInfo();
        pageInfo.setList(resultDTOList);
        log.info("执行列表分页查询完成，准备返回的结果为：" + JSON.toJSONString(pageInfo));
        return new Result(true, 20000, "列表分页查询成功", pageInfo);
    }


    /**
     * @title: save
     * @description: 数据插入
     * @params: [ paramsDTO ]
     * @return: org.springframework.http.ResponseEntity
     * @createTime: 2022-03-14
     * @version: 1.0
     * @author: l22886
     */
    @ApiOperation(value = "数据插入", notes = "数据插入")
    @ApiImplicitParams({@ApiImplicitParam(name = "paramsDTO", value = "实体参数信息", required = true, dataType = "PtDept", paramType = "body")})
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public Result save(@RequestBody PtDeptDTO paramsDTO) {
        log.info("准备执行 数据插入，传入的参数为：" + JSON.toJSONString(paramsDTO));
        //执行
        Integer result = ptDeptService.insertDto(paramsDTO);
        log.info("执行 数据插入完成，准备返回的结果为：" + JSON.toJSONString(result));
        return new Result(true, 20000, "数据插入成功", result);
    }

    /**
     * @title: update
     * @description: 数据修改
     * @params: [ paramsDTO ]
     * @return: org.springframework.http.ResponseEntity
     * @createTime: 2022-03-14
     * @version: 1.0
     * @author: l22886
     */
    @ApiOperation(value = "数据修改", notes = "数据修改")
    @ApiImplicitParams({@ApiImplicitParam(name = "paramsDTO", value = "实体参数信息", required = true, dataType = "PtDept", paramType = "body")})
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public Result update(@RequestBody PtDeptDTO paramsDTO) {
        log.info("准备执行 数据修改，传入的参数为：" + JSON.toJSONString(paramsDTO));
        //执行
        Integer result = ptDeptService.updateDto(paramsDTO);
        log.info("执行 数据修改完成，准备返回的结果为：" + JSON.toJSONString(result));
        return new Result(true, 20000, "数据修改成功", result);
    }

    /**
     * @title: delete
     * @description: 数据删除
     * @params: [ id ]
     * @return: org.springframework.http.ResponseEntity
     * @createTime: 2022-03-14
     * @version: 1.0
     * @author: l22886
     */
    @ApiOperation(value = "数据删除", notes = "数据删除")
    @ApiImplicitParams({@ApiImplicitParam(name = "paramsDTO", value = "实体参数信息", required = true, dataType = "PtDept", paramType = "body")})
    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    public Result delete(@RequestBody PtDeptDTO paramsDTO) {
        log.info("准备执行 数据删除，传入的参数为：" + JSON.toJSONString(paramsDTO));
        //执行
        Integer result = ptDeptService.deleteDto(paramsDTO);
        log.info("执行 数据删除 完成，准备返回的结果为：" + JSON.toJSONString(result));
        return new Result(true, 20000, "数据删除", result);
    }


    @RequestMapping(value = "/qyeryChidrenDeptList", method = RequestMethod.POST)
    public Result qyeryChidrenDeptList(@RequestBody PtDeptDTO ptDeptDTO) {
        List<PtDeptDTO> ptDeptDTOS;
        if (StringUtils.hasText(ptDeptDTO.getAppId()) && ptDeptDTO.getAppId().equals("e-sign-platform")){
            String domain = CommonUtil.getActivUser().getAccount();
            ptDeptDTOS = ptDeptService.getAuthorizeDeptTree(ptDeptDTO, domain);
        } else {
            ptDeptDTOS = ptDeptService.qyeryChidrenDeptList(ptDeptDTO);
        }
        return new Result(true, StatusCodeEnum.SEARCH_SUCCESS, ptDeptDTOS);
    }

    @RequestMapping(value = "/getAuthorizeChildTree", method = RequestMethod.GET)
    public Result getAuthorizeChildTree(@RequestParam(name = "appId") String appId, @RequestParam(name = "workerId") String workerId){
        PtDeptDTO root = ptDeptService.getAuthorizeChildTree(appId, workerId);
        List<PtDeptDTO> ptDeptDTOS = ptDeptService.changeRootToChildList(root);
        return new Result(true, StatusCodeEnum.SEARCH_SUCCESS, ptDeptDTOS);
    }

    /**
     * 下载部门信息（授权用户）
     * @param ptDeptDTO
     * @param response
     */
    @RequestMapping(value = "/downloadDeptData", method = RequestMethod.POST)
    public void downloadDeptData(@RequestBody PtDeptDTO ptDeptDTO,
                                 HttpServletResponse response) {
        try {
            List<PtDeptDTO> ptDeptDTOS;
            if (StringUtils.hasText(ptDeptDTO.getAppId()) && ptDeptDTO.getAppId().equals("e-sign-platform")){
                String domain = CommonUtil.getActivUser().getAccount();
                ptDeptDTOS = ptDeptService.getAllAuthorizedDeptList(ptDeptDTO.getAppId(), domain);
            }
            else {
               ptDeptDTOS = ptDeptService.qyeryChidrenDeptList(ptDeptDTO);
            }

            ExcelFileDTO excelFileDTO = new ExcelFileDTO();
            excelFileDTO.setAppId("ptability-manage");
            excelFileDTO.setDataList(ptDeptDTOS);
            excelFileDTO.setFileName("部门授权用户信息表");
            excelFileDTO.setTemplateCode("PT_DEPT_EXPORT");
            File downLoadFile = ptEnumService.getExcelFile(excelFileDTO);
            FileInputStream inputStream = new FileInputStream(downLoadFile);
            byte[] buffer = new byte[(int) downLoadFile.length()];
            inputStream.read(buffer);
            inputStream.close();
            FileUtil.del(downLoadFile);
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding(Charsets.UTF_8.name());
            response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(downLoadFile.getName(), Charsets.UTF_8.name()));
            response.setHeader("issuccess", "1");
            response.setHeader("Access-Control-Expose-Headers", "Content-disposition,issuccess");
            IoUtil.write(response.getOutputStream(), true, buffer);
        } catch (IOException e) {
            log.error("导出excel报错,原因:{}", e.getMessage());
            throw new BusinessException(StatusCodeEnum.REQ_DOWNLOAD_FAIL);
        }
    }

    @ApiOperation(value = "部门信息导入", notes = "部门信息导入")
    @ApiImplicitParams({@ApiImplicitParam(name = "file", value = "导入数据文件", required = true, dataType = "MultipartFile", paramType = "body")})
    @RequestMapping(value = "/importDeptSet", method = RequestMethod.POST)
    public ResultData importDeptSet(@RequestParam(value = "appId") String appId,
                                    @RequestParam(value = "file") MultipartFile file) {
        ptDeptService.importDeptSetList(appId, file);
        return ResultData.success("导入成功");
    }

    @ApiOperation(value = "导入部门体系信息", notes = "导入部门体系信息")
    @ApiImplicitParams({@ApiImplicitParam(name = "file", value = "导入数据文件", required = true, dataType = "MultipartFile", paramType = "body")})
    @RequestMapping(value = "/importDeptSystemSet", method = RequestMethod.POST)
    public ResultData importDeptSystemSet(@RequestParam(value = "file") MultipartFile file) {
        ptDeptService.importDeptSystemSet(file);
        return ResultData.success("导入成功");
    }

    /**
     * 下载部门体系
     * @param ptDeptDTO
     * @param response
     */
    @RequestMapping(value = "/downloadDeptSystemData", method = RequestMethod.POST)
    public void downloadDeptSystemData(@RequestBody PtDeptDTO ptDeptDTO,
                                       HttpServletResponse response) {
        try {
            ptDeptDTO.setDeptStatus(1);
            List<PtDeptDTO> ptDeptDTOS = ptDeptService.selectFuzzyByDto(ptDeptDTO);
            ExcelFileDTO excelFileDTO = new ExcelFileDTO();
            excelFileDTO.setAppId("ptability-manage");
            excelFileDTO.setDataList(ptDeptDTOS);
            excelFileDTO.setFileName("部门体系信息表");
            excelFileDTO.setTemplateCode("PT_DEPT_SYSTEM_EXPORT");
            File downLoadFile = ptEnumService.getExcelFile(excelFileDTO);
            FileInputStream inputStream = new FileInputStream(downLoadFile);
            byte[] buffer = new byte[(int) downLoadFile.length()];
            inputStream.read(buffer);
            inputStream.close();
            FileUtil.del(downLoadFile);
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding(Charsets.UTF_8.name());
            response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(downLoadFile.getName(), Charsets.UTF_8.name()));
            response.setHeader("issuccess", "1");
            response.setHeader("Access-Control-Expose-Headers", "Content-disposition,issuccess");
            IoUtil.write(response.getOutputStream(), true, buffer);
        } catch (IOException e) {
            log.error("导出excel报错,原因:{}", e.getMessage());
            throw new BusinessException(StatusCodeEnum.REQ_DOWNLOAD_FAIL);
        }
    }

    /**
     * 下载部门数据
     * @param ptDeptDTO
     * @param response
     */
    @RequestMapping(value = "/downloadDeptValidData", method = RequestMethod.POST)
    public void downloadDeptValidData(@RequestBody PtDeptDTO ptDeptDTO,
                                       HttpServletResponse response) {
        try {
            List<PtDeptDTO> ptDeptDTOS = ptDeptService.selectByDto(ptDeptDTO);
            ExcelFileDTO excelFileDTO = new ExcelFileDTO();
            excelFileDTO.setAppId("ptability-manage");
            excelFileDTO.setDataList(ptDeptDTOS);
            excelFileDTO.setFileName("部门体系信息表");
            excelFileDTO.setTemplateCode("PT_DEPT_SYSTEM_EXPORT");
            File downLoadFile = ptEnumService.getExcelFile(excelFileDTO);
            FileInputStream inputStream = new FileInputStream(downLoadFile);
            byte[] buffer = new byte[(int) downLoadFile.length()];
            inputStream.read(buffer);
            inputStream.close();
            FileUtil.del(downLoadFile);
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding(Charsets.UTF_8.name());
            response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(downLoadFile.getName(), Charsets.UTF_8.name()));
            response.setHeader("issuccess", "1");
            response.setHeader("Access-Control-Expose-Headers", "Content-disposition,issuccess");
            IoUtil.write(response.getOutputStream(), true, buffer);
        } catch (IOException e) {
            log.error("导出excel报错,原因:{}", e.getMessage());
            throw new BusinessException(StatusCodeEnum.REQ_DOWNLOAD_FAIL);
        }
    }

    /**
     * feign调用接口
     * @param deptId
     * @return
     */
    @GetMapping("/getDeptByDeptId")
    public PtDept getDeptByDeptId(@RequestParam Integer deptId){
        return ptDeptService.getById(deptId);
    }

    @RequestMapping(value = "/syncPtDept", method = RequestMethod.POST)
    public Result syncePtDept(@RequestBody PtDept ptDept) {
        ptDeptService.syncPtDept(true);
        return new Result(true, 20000, "同步成功");
    }

    @RequestMapping(value = "/setDeptUserRole", method = RequestMethod.POST)
    public Result setDeptUserRole(@RequestBody PtDeptDTO ptDeptDTO) {
        Optional.ofNullable(ptDeptDTO.getAppId()).orElseThrow(() -> new AppBusinessException("appId不能为空"));
        Optional.ofNullable(ptDeptDTO.getDeptId()).orElseThrow(() -> new AppBusinessException("deptId不能为空"));
        String domain = null;
        if (ptDeptDTO.getAppId().equals("e-sign-platform")){
            domain = CommonUtil.getActivUser().getAccount();
        }
        ptDeptService.setDeptUserRole(ptDeptDTO, domain);
        return new Result(true, StatusCodeEnum.NORMAL);

    }

    /**
     * 获取部门对应的体系
     * @param deptId
     * @return
     */
    @GetMapping("/getDeptSystem")
    public String getDeptSystem(@RequestParam Integer deptId){
        PtDept ptDept = ptDeptService.getById(deptId);
        return PtEnumCache.getEnumDataInRedis("ptability-manage", "DEPT_SYSTEM", String.valueOf(ptDept.getDeptSystem()));
    }

    /**
     * 获取所有部门
     * @return
     */
    @GetMapping("/getDeptList")
    public List<PtDept> getDeptList(){
        return ptDeptService.list(new QueryWrapper<PtDept>().lambda().eq(PtDept::getDeptStatus, 1));
    }

    /**
     * 查询部门树
     * @param deptIds
     * @return
     */
    @GetMapping("/queryDeptTreeSelection")
    public Result queryDeptTreeSelection(String deptIds){
        List<OptionsDTO> result = ptDeptService.queryDeptTreeSelection(deptIds);
        return new Result(true, StatusCodeEnum.NORMAL, result);
    }

    /**
     * 根据部门链路名称获取一级部门id
     * @param deptNameChain
     * @return
     */
    @GetMapping("/getDept1IdByDeptNameChain")
    public Result getDept1IdByDeptNameChain(String deptNameChain){
        deptNameChain = BusiEnumDefine.DEPT_XINHUASAN + deptNameChain;
        PtDept ptDept = ptDeptService.getOne(new QueryWrapper<PtDept>().lambda()
                .eq(PtDept::getDeptNameChain, deptNameChain)
                .eq(PtDept::getDeptStatus, 1));
        String deptCodeChain = ptDept.getDeptCodeChain();
        String[] deptCodeArr = deptCodeChain.split("/");
        String deptId = deptCodeArr[1];
        return new Result(true, StatusCodeEnum.NORMAL, deptId);
    }

    /**
     * feign调用获取授权用户，如果没有授权用户就获取部门主管和主管工号
     * @param searchDeptsManagersBO
     * @return
     */
    @PostMapping("/getDeptsManagers")
    public ResultData<List<DeptManagerBO>> getDeptsManagers(@Valid @RequestBody SearchDeptsManagersBO searchDeptsManagersBO){
        try {
            return ResultData.data(ptDeptService.getDeptsManagers(searchDeptsManagersBO));
        } catch (Exception e) {
            log.error("feign调用获取部门主管和主管工号报错:{}", JSONUtil.toJsonStr(e));
            return ResultData.fail("feign调用获取部门主管和主管工号报错:{}",e.getMessage());
        }
    }

    /**
     * 获取特殊部门集合
     * @return 特殊部门集合
     */
    @PostMapping("/getSpecialDeptCodes")
    public ResultData<List<EosSpecialDeptDto>> getSpecialDeptCodes(){
        try {
            return ResultData.data(ptDeptService.getSpecialDeptCodesFromEos());
        } catch (Exception e) {
            log.error("获取特殊部门集合报错:{}", JSONUtil.toJsonStr(e));
            return ResultData.fail("获取特殊部门集合报错:{}",e.getMessage());
        }
    }
}
